package top.someapp.applib.json;

import androidx.annotation.NonNull;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import top.someapp.applib.AppException;

/**
 * @author zwz
 * Created on 2020-07-17
 */
public class JsonHelperImpl implements JsonHelper {

    protected JsonHelperImpl() {
        // for subclass overwrite.
        // check if Gson in classpath
        try {
            Class<?> clz = Class.forName("com.google.gson.Gson");
            if (clz != null) {

            }
        } catch (ClassNotFoundException e) {
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> Map<T, Object> toMap(@NonNull String json) {
        JSONObject jsonObject = new JSONObject(json);
        return (Map<T, Object>) jsonObject.toMap();
    }

    private static String readAsString(Reader reader) {
        boolean ok = false;
        CharArrayWriter writer = new CharArrayWriter(1024);
        char[] chars = new char[1024];
        try {
            for (int len = -1; (len = reader.read(chars)) > 0; ) {
                writer.write(chars, 0, len);
            }
            writer.flush();
            ok = true;
        } catch (IOException ignored) {
        } finally {
            writer.close();
        }
        return ok ? writer.toString() : "";
    }

    @Override
    public <T> Map<T, Object> toMap(@NonNull Reader reader) {
        String json = readAsString(reader);
        return toMap(json);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> List<T> toList(@NonNull String json) {
        JSONArray jsonArray = new JSONArray(json);
        return (List<T>) jsonArray.toList();
    }

    @Override
    public <T> List<T> toList(@NonNull Reader reader) {
        String json = readAsString(reader);
        return toList(json);
    }

    @Override
    public <T> T toBean(@NonNull String json, @NonNull Type beanType) {
        throw new AppException("Not implements!");
    }

    @Override
    public String toJSONString(Map<String, Object> map) {
        if (map == null) {
            return null;
        }
        if (map.isEmpty()) {
            return "{}";
        }
        JSONObject jsonObject = new JSONObject(map);
        return jsonObject.toString();
    }

    @Override
    public String toJSONString(Collection<?> list) {
        if (list == null) {
            return null;
        }
        if (list.isEmpty()) {
            return "[]";
        }
        JSONArray jsonArray = new JSONArray(list);
        return jsonArray.toString();
    }

    @Override
    public String toJSONString(Object obj) {
        return toJSONString(obj, null, true, false);
    }

    @SuppressWarnings("unchecked")
    @Override
    public String toJSONString(Object obj, String jsonIfNull, boolean includeNulls,
        boolean jsNumberSafe) {
        if (obj == null) {
            return jsonIfNull;
        }

        if (obj instanceof Map) {
            return toJSONString((Map) obj);
        }
        if (obj instanceof Collection<?>) {
            return toJSONString((Collection<?>) obj);
        }

        JSONArray jsonArray = new JSONArray(new Object[]{obj});
        String json = null;
        try {
            json = jsonArray.get(0).toString();
        } catch (JSONException ignored) {
        }
        return json == null ? jsonIfNull : json;
    }

    @Override
    public String shortJSONString(Object obj) {
        return toJSONString(obj, null, true, false);
    }

    @Override
    public String safeJSONString(Object obj) {
        return toJSONString(obj, "", true, true);
    }
}
